import generate from "@babel/generator";
import {parse} from "@babel/parser";
import traverse, {Node, NodePath} from "@babel/traverse";
import {binaryExpression} from "@babel/types";


type Transformer = (path: NodePath) => void


// a+b ==> a-b
const t1 = function (path: NodePath) {
    if (path.isBinaryExpression({operator: "+"})) {
        path.replaceWith(
            binaryExpression("-", path.node.left, path.node.right)
        )
    }
}
// a/b ==> a*b
const t2 = function (path: NodePath) {
    if (path.isBinaryExpression({operator: "/"})) {
        path.replaceWith(
            binaryExpression("*", path.node.left, path.node.right)
        )
    }
}
// a==b ==> a===b
const t3 = function (path: NodePath) {
    if (path.isBinaryExpression({operator: "=="})) {
        path.replaceWith(
            binaryExpression("===",
                path.node.left, path.node.right
            )
        )
    }
}

// logger transformer
const t4 = function (path: NodePath) {
    console.log(path.type)
}

function compose(...trans: Transformer[]): Transformer {
    return (path: NodePath) => trans.forEach(t => t(path))
}


class TransformerRunner {
    constructor(readonly t: Transformer) {
    }

    runWithAst(node: Node | Node[]): Node | Node[] {
        const transOption = {
            enter: this.t
        }
        traverse(node, transOption)
        return node
    }
}


const runner = new TransformerRunner(compose(
    t1,
    // t2,  // 随意组合
    t3,
))

const runnerWithLogger = new TransformerRunner(compose(
    t1, t2, t3, t4)
)


let from = `const t = (a, b) => console.log(a + b, a == b, a / c)`;

console.log(from);
const ast = runner.runWithAst(parse(from))
console.log(generate(ast as Node).code);


runnerWithLogger.runWithAst(parse(from))
